# ======================================================================
# Project:    Closed borders, closed minds? COVID-related border closures,
#             EU support and hostility towards immigrants
#
# Script:     Figure 1
#
# Authors:    Lisa Herbig (l.j.herbig@uva.nl)
#             Asli Unan (a.unan@uva.nl)
#
# Date:       2025-03-24
# ======================================================================

# Description:
# This script generates Figure 1 creating the map illustrating the different border regions

# ----------------------------------------------------------------------
# Load libraries
# ----------------------------------------------------------------------

library(sf)
library(dplyr)
library(ggplot2)
library(writexl)

# Germany outer borders ---------------------------------------------------

#Open Kreis shapefile

setwd("~/Library/CloudStorage/Dropbox/COVIDEU/WP 1 Borders & Mobility/Analysis/Data/Spatial/WP1 Kreise spatial/vg2500_geo84")

# Read shapefile for Germany
germ_sh <- read_sf("vg2500_krs.shp")
plot(st_geometry(germ_sh))

#Dissolve inner borders and keep outer lines

#First check it out
st_is_valid(germ_sh) 

germ_sh_union <- germ_sh %>% 
  st_make_valid() %>% 
  st_union()

plot(st_geometry(germ_sh_union)) 

st_write(germ_sh_union, "Germany_borders.shp")


#Calculate centroids
germ_cent <- st_centroid(germ_sh)
plot(st_geometry(germ_cent))

# plot both together
library("ggplot2")
ggplot() + 
  geom_sf(data = germ_sh, fill = 'white') +
  geom_sf(data = germ_cent, color = 'red') 

#Create border shapefile
table(st_is_valid(germ_sh))

germ_sh_union <- germ_sh %>% 
  st_union()

#and plot it
ggplot() + 
  geom_sf(data = germ_sh_union, fill = 'white') +
  geom_sf(data = germ_cent, color = 'red') 

#Calculate distances
dist <- st_distance(st_cast(germ_sh_union, "MULTILINESTRING"), germ_cent)
head(dist[1,])

# Assuming the first row represents the minimum distance for each point to the border
min_dist <- apply(dist, 2, min) 

# Create a color column based on the distance
germ_cent$color <- ifelse(min_dist <= 25000, 'blue', 'red')

# Plot both together with the specified colors
ggplot() + 
  geom_sf(data = germ_sh, fill = 'white') +
  geom_sf(data = germ_sh_union, color = 'black', size = 0.5) + # Adding the border as black lines
  geom_sf(data = germ_cent, aes(color = color)) +
  scale_color_identity() # Use the color column directly


##############Creating map with 25km border criteria

# Assuming your working directory is already set to where "vg2500_krs.shp" is located

# Read shapefile for Germany Kreis
germ_sh <- read_sf("vg2500_krs.shp")

# Make valid
germ_sh <- germ_sh %>% st_make_valid()

# Dissolve all internal Kreis boundaries to create a single polygon for the outer border
germ_sh_union <- germ_sh %>% 
  st_union() %>% 
  st_make_valid()

# Calculate centroids of the original Kreis (internal borders are retained here)
germ_cent <- st_centroid(germ_sh)

# Calculate distances from centroids to the outer border
dist <- st_distance(st_cast(germ_sh_union, "MULTILINESTRING"), germ_cent)

# Assuming the first row represents the minimum distance for each point to the border
min_dist <- apply(dist, 2, min)

# Add a color column to centroids based on their distance to the outer border
germ_cent$color <- ifelse(min_dist <= 25000, 'blue', 'red')

# Plot both together: Kreis borders and centroids with colors based on proximity to the outer border
ggplot() + 
  geom_sf(data = germ_sh, fill = NA, color = 'grey') + # Show internal borders in grey
  geom_sf(data = germ_cent, aes(color = color), size = 2) + # Centroids colored based on proximity to outer border
  scale_color_identity() + # Use the color column directly
  labs(title = "Germany Kreis with Centroids Colored Based on Proximity to Border",
       subtitle = "Centroids within 25km of the border are blue, others are red") +
  theme_minimal()

#############SCRIPT TO ADD NEIGHBORING COUNTRIES BORDERS

setwd("~/Library/CloudStorage/Dropbox/COVIDEU/WP 1 Borders & Mobility/Analysis/Data/Spatial/WP1 Kreise spatial/Shapefiles - GER and neighboring countries")
# Define a list of neighboring countries shapefiles
neighboring_countries <- c("gadm41_AUT_0.shp", "gadm41_BEL_0.shp", "gadm41_CHE_0.shp", "gadm41_DNK_0.shp",
                           "gadm41_FRA_0.shp","gadm41_LUX_0.shp", "gadm41_NLD_0.shp","gadm41_POL_0.shp","gadm41_CZE_0.shp" )

# Load and combine all neighboring countries' shapefiles
neighbors <- lapply(neighboring_countries, read_sf) %>% 
  do.call(rbind, .)

# Calculate the distance from each Kreis centroid to the neighboring countries
distances_to_neighbors <- st_distance(germ_cent, neighbors)

# For each Kreis, find the minimum distance and the corresponding country
min_distances <- apply(distances_to_neighbors, 1, min)
closest_country_indices <- apply(distances_to_neighbors, 1, which.min)
closest_countries <- neighbors$COUNTRY[closest_country_indices] 

# Add the closest country information to the germ_cent DataFrame
germ_cent$closest_country <- closest_countries

germ_cent <- data.frame(dist = as.vector(dist)/1000, #from meters to km
                        germ_cent)

hist(germ_cent$dist)

write.csv(germ_cent,"Kreise_distance-to-border-and-nearest-country.csv", row.names = FALSE)


# Assuming distances_to_neighbors and neighbors are correctly set up
# neighbors should have a column named COUNTRY or similar, which holds the country names or codes

# Ensure neighbors dataframe has a 'COUNTRY' column with correct country identifiers
print(head(neighbors$COUNTRY))

# Recalculate min_distances if necessary
min_distances <- apply(distances_to_neighbors, 1, min)
# Convert distances to kilometers
min_distance_km <- min_distances / 1000

# Find the closest country for each Kreis
closest_country_indices <- apply(distances_to_neighbors, 1, which.min)
closest_countries <- neighbors$COUNTRY[closest_country_indices]

# Add the closest country and min_distance_km back into germ_cent
germ_cent$closest_country <- closest_countries
germ_cent$min_distance_km <- min_distance_km

# Define colors for each country
country_colors <- c(France = "orange", Netherlands = "blue", Belgium = "yellow", Poland = "black",
                    Czechia = "green", Austria = "brown", Switzerland = "purple", Denmark = "red", Luxembourg = "darkgreen")

# Assign color based on closest country within 25km, otherwise black
germ_cent$color <- sapply(1:nrow(germ_cent), function(i) {
  if(germ_cent$min_distance_km[i] <= 25) {
    return(country_colors[germ_cent$closest_country[i]])
  } else {
    return("grey")
  }
})

# Left join germ_cent information back to germ_sh for plotting
germ_sh <- germ_sh %>%
  left_join(germ_cent, by = "RS")  # Assuming RS is the correct unique identifier

#CREATE FIGURE 1
ggplot() +
  geom_sf(data = germ_sh, aes(fill = color), color = NA, size = 0.1, show.legend = 'point') + # Fill Kreise borders
  geom_sf(data = germ_sh, aes(color = color), size = 4) +  # Color the borders
  geom_sf(data = germ_sh, aes(geometry = geometry.y, color = color), size = 2) + # Plot centroids
  scale_fill_identity() + # Use the fill color directly for Kreise borders
  scale_color_identity() + # Use the color directly for centroids
  labs(title = "Germany Kreise Proximity to Neighboring Countries",
       subtitle = "Kreise and centroids colored by closest neighboring country within 25km, others in grey") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5, size = 11),
        plot.title.position = "plot",   # Move title outside plot area
        panel.grid.major = element_blank(),   # Remove grid lines
        panel.grid.minor = element_blank(),
        axis.text = element_blank(),          # Remove coordinates
        axis.ticks = element_blank(),
        axis.title = element_blank())
